package butines.game;


public class StateMachine<Entity> {

	private Entity owner;

	private State<Entity> currentState;
	private State<Entity> previousState;
	private State<Entity> globalState;

	public StateMachine(Entity owner) {
		this.owner = owner;
	}

	public void changeState(State<Entity> newState) {
		if (currentState != null) {
			previousState = currentState;
//			System.out.println(owner + " - " + getStateName() + " | leave");
			currentState.leave(owner);
		}
		currentState = newState;
		if (currentState != null) {
//			System.out.println(owner + " - " + getStateName() + " | enter");
			currentState.enter(owner);
		}
	}

	public void revertToPreviousState() {
		changeState(previousState);
	}

	public void update() {
		if (globalState != null) {
			globalState.execute(owner);
		}
		if (currentState != null) {
			currentState.execute(owner);
		}
	}

	public String getStateName() {
		return currentState == null ? "none" : currentState.getClass().getSimpleName();
	}

	public State<Entity> getCurrentState() {
		return currentState;
	}

	public void setCurrentState(State<Entity> currentState) {
		this.currentState = currentState;
	}

	public State<Entity> getPreviousState() {
		return previousState;
	}

	public void setPreviousState(State<Entity> previousState) {
		this.previousState = previousState;
	}

	public State<Entity> getGlobalState() {
		return globalState;
	}

	public void setGlobalState(State<Entity> globalState) {
		this.globalState = globalState;
	}

	public boolean inState(Class<?> stateClass) {
		return currentState != null && currentState.getClass() == stateClass;
	}

	private boolean fireMessage(State<Entity> state, Message message) {
		if (state == null) {
			return false;
		}
		return state.onMessage(message);
	}
	
	public boolean handlerMessage(Message message) {
		// first see if the current state is valid and that it can handle the message
		if (fireMessage(currentState, message)) {
			return true;
		}

		// if not, and if a global state has been implemented, send the message to the global state
		if (fireMessage(globalState, message)) {
			return true;
		}

		return false;
	}
}
